/**
  ******************************************************************************
  * @file    GPIO/GPIO_IOToggle/stm32f4xx_it.c 
  * @author  MCD Application Team
  * @version V1.4.0
  * @date    04-August-2014
  * @brief   Main Interrupt Service Routines.
  *          This file provides template for all exceptions handler and 
  *          peripherals interrupt service routine.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2013 STMicroelectronics</center></h2>
  *
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software 
  * distributed under the License is distributed on an "AS IS" BASIS, 
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_it.h"

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "beep.h"
#include "usart.h"
#include "ser_as608.h"


typedef struct Message
 {
     char message_type;		//0--传感器数据和设备状态、1--控制指令
     char message_content[400];
     int sum_check;	//strlen(message_content)//和校验
 }Message;

extern Message message;
extern char message_flag;

extern char key1_status;
extern char key2_status;
extern char key3_status;

extern char mtri_key_value;//矩阵键盘键值
extern char password_input[12];
extern char password[2][12];
extern char password_input_index;
extern char password_pattern;
extern char password_flag;
extern char pwd_change_flag;
extern char input_pwd_change_flag;

extern char door_flag;


u16 tim6_period_cnt;	//按键复用计时器计数值
int usart2_buf_index= 0;// 消息字符串的下标
char usart2_buf[600]={0};// 消息字符串缓冲区

/** @addtogroup STM32F4xx_StdPeriph_Examples
  * @{
  */

/** @addtogroup GPIO_IOToggle
  * @{
  */

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/******************************************************************************/
/*            Cortex-M4 Processor Exceptions Handlers                         */
/******************************************************************************/

/**
  * @brief   This function handles NMI exception.
  * @param  None
  * @retval None
  */
void NMI_Handler(void)
{
}

/**
  * @brief  This function handles Hard Fault exception.
  * @param  None
  * @retval None
  */
void HardFault_Handler(void)
{
  /* Go to infinite loop when Hard Fault exception occurs */
  while (1)
  {
  }
}

/**
  * @brief  This function handles Memory Manage exception.
  * @param  None
  * @retval None
  */
void MemManage_Handler(void)
{
  /* Go to infinite loop when Memory Manage exception occurs */
  while (1)
  {
  }
}

/**
  * @brief  This function handles Bus Fault exception.
  * @param  None
  * @retval None
  */
void BusFault_Handler(void)
{
  /* Go to infinite loop when Bus Fault exception occurs */
  while (1)
  {
  }
}

/**
  * @brief  This function handles Usage Fault exception.
  * @param  None
  * @retval None
  */
void UsageFault_Handler(void)
{
  /* Go to infinite loop when Usage Fault exception occurs */
  while (1)
  {
  }
}

/**
  * @brief  This function handles SVCall exception.
  * @param  None
  * @retval None
  */
//void SVC_Handler(void)
//{
//}

/**
  * @brief  This function handles Debug Monitor exception.
  * @param  None
  * @retval None
  */
void DebugMon_Handler(void)
{
}

/**
  * @brief  This function handles PendSVC exception.
  * @param  None
  * @retval None
  */
//void PendSV_Handler(void)
//{
//}

/**
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
  */
//void SysTick_Handler(void)
//{
//}

/******************************************************************************/
/*                 STM32F4xx Peripherals Interrupt Handlers                   */
/*  Add here the Interrupt Handler for the used peripheral(s) (PPP), for the  */
/*  available peripheral interrupt handler's name please refer to the startup */
/*  file (startup_stm32f40xx.s/startup_stm32f427x.s/startup_stm32f429x.s).    */
/******************************************************************************/

/**
  * @brief  This function handles PPP interrupt request.
  * @param  None
  * @retval None
  */
/*void PPP_IRQHandler(void)
{
}*/

/******************************************************************************
函数名：TIM6_DAC_IRQHandler
功能：定时器6中断处理函数---主要用作判断按键消抖判断
输入参数：无
输出参数：无
其他说明：
******************************************************************************/
void TIM6_DAC_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM6, TIM_IT_Update) == SET)
	{
		TIM_ClearITPendingBit(TIM6, TIM_IT_Update);
		tim6_period_cnt++;
	}
}

/*****************************************************************************************
函数名：EXTI4_IRQHandler
功能：外部5-9中断处理函数
输入参数：无
输出参数：无
其他说明：按键1外部中断
*****************************************************************************************/

void EXTI4_IRQHandler(void)
{	
	
	static char key1_flag = 0;
	
	EXTI_ClearITPendingBit(EXTI_Line4);//清除中断标志
	if(key1_flag == 0)
	{
		key1_flag = 1;
		TIM_Cmd(TIM6, ENABLE);//基本定时器6开始计时
	}
	else if(key1_flag == 1)
	{
		key1_flag = 0;
		TIM_Cmd(TIM6, DISABLE);//基本定时器6停止计时
		if(tim6_period_cnt > 6)//超过60ms为有效按下
		{
			key1_status = 1;
		}
		tim6_period_cnt = 0;	
	}
	
}

/*****************************************************************************************
函数名：EXTI9_5_IRQHandler
功能：外部5-9中断处理函数
输入参数：无
输出参数：无
其他说明：按键2-3外部中断
*****************************************************************************************/
void EXTI9_5_IRQHandler(void)
{
	static char key2_flag = 0;
	static char key3_flag = 0;
	
	if(EXTI_GetITStatus(EXTI_Line5) == SET)//判断哪个外部线产生的中断
	{	
		EXTI_ClearITPendingBit(EXTI_Line5);//清除中断标志
		if(key2_flag == 0)
		{
			key2_flag = 1;
			TIM_Cmd(TIM6, ENABLE);//基本定时器6开始计时
		}
		else if(key2_flag == 1)
		{
			key2_flag = 0;
			TIM_Cmd(TIM6, DISABLE);//基本定时器6停止计时
			if(tim6_period_cnt > 6)//超过60ms为有效按下
			{
				key2_status = 1;
			}
			tim6_period_cnt = 0;
		}
	}
	else if(EXTI_GetITStatus(EXTI_Line6) == SET)//判断哪个外部线产生的中断
	{
		EXTI_ClearITPendingBit(EXTI_Line6);//清除中断标志
		if(key3_flag == 0)
		{
			key3_flag = 1;
			TIM_Cmd(TIM6, ENABLE);//基本定时器6开始计时
		}
		else if(key3_flag == 1)
		{
			key3_flag = 0;
			TIM_Cmd(TIM6, DISABLE);//基本定时器6停止计时
			if(tim6_period_cnt > 6 )//高于60ms消抖
			{
				key3_status = 1;
			}
			tim6_period_cnt = 0;
		}
	}
}

/******************************************************************************
函数名：USART1_IRQHandler
功能：串口1中断处理函数,
输入参数：无
输出参数：无
其他说明：pd5->tx,	pd6->rx
******************************************************************************/

//注意,读取USARTx->SR能避免莫名其妙的错误 
//接收状态
//bit15，	接收完成标志
//bit14，	接收到0x0d
//bit13~0，	接收到的有效字节数目

extern u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
extern u16 USART_RX_STA;    //接收状态标记	
static char buf[10] = "";
extern u16 ID;

//void USART1_IRQHandler(void)                 // 串口1中断服务程序
//{
//    static u8 res;
//    static u8 *p = (u8 *)buf;
//
//    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  // 检查接收中断（数据应以0x0d 0x0a结尾）
//    {
//        res = USART_ReceiveData(USART1); // 读取接收到的数据
//        if ((USART_RX_STA & 0x8000) == 0) // 检查接收是否未完成
//        {
//            if (USART_RX_STA & 0x4000) // 如果已接收回车符
//            {
//                if (res != '\n') // 如果不是换行符，重置状态
//                {
//                    USART_RX_STA = 0;
//                }
//                else // 如果是换行符，标记接收完成
//                {
//                    USART_RX_STA |= 0x8000;
//                }
//            }
//            else // 如果回车符尚未接收
//            {
//                if (res == '\r') // 如果接收到回车符，设置标志
//                {
//                    USART_RX_STA |= 0x4000;
//                }
//                else // 否则，将字符存储到缓冲区
//                {
//                    if (USART_RX_STA < USART_REC_LEN)
//                    {
//                        *p++ = res;
//                        USART_RX_STA++;
//                        if (USART_RX_STA >= USART_REC_LEN) // 如果缓冲区满，重置状态
//                        {
//                            USART_RX_STA = 0;
//                            p = (u8 *)buf; // 将指针重置到缓冲区开头
//                        }
//                    }
//                }
//            }
//        }
//        // 处理ID（假设此部分正确且需要）
//        ID &= ~(1 << 16); // 清除ID的第17位
//        ID |= buf[0]; // 将缓冲区的第一个字节与ID进行按位或运算
//        if (buf[1] != 0) {
//            ID = (ID << 8) + buf[1]; // 如果存在第二个字节，将其左移并相加
//        }
//        memset(buf, 0, sizeof(buf)); // 清空缓冲区
//        p = (u8 *)buf; // 将指针重置到缓冲区开头
//    }
//}

/******************************************************************************
函数名：USART2_IRQHandler
功能：串口2中断处理函数,通过WIFI接收数据实现转发
输入参数：无
输出参数：无
其他说明：pd5->tx,	pd6->rx
******************************************************************************/
int get_length(char *str,int index)
{
    char *p = str;
    int count = 0;
    while(index--)
    {
        if(*p++ != '\0')
        {
            count ++;
        }
    }
    return count;
}

//void USART2_IRQHandler(void)
//{
//	if(USART_GetITStatus(USART2, USART_IT_RXNE) == SET)//-------------------接收数据中断
//	{
//		USART_ClearITPendingBit(USART2, USART_IT_RXNE);	//清除接收中断标志
//		USART_SendData(USART1, USART_ReceiveData(USART2));//将串口二接收到的数据通过串口一发送出去
//		usart2_buf[usart2_buf_index++] = USART_ReceiveData(USART2);		
//	}
//	if(USART_GetITStatus(USART2, USART_IT_IDLE) == SET)//-------------------总线空闲中断
//	{
//		USART_ReceiveData(USART2);		//总线空闲中断通过读取数据来清除中断标志
////		printf("#%c#%c#%c#%c#%c#%c#",usart2_buf[0],usart2_buf[1],usart2_buf[2],usart2_buf[3],usart2_buf[10],usart2_buf[11]);
//		//只获取有效数据，防止AT指令被写入buf缓存区
//		if(strncmp(usart2_buf+2,"+IPD",4) == 0)
//		{	
//			printf("11111111111111111111111111111111111111\n");
//			memset(&message,0,sizeof(message));	//清空消息结构体
//			message = *(Message*)(usart2_buf + 13);	//接收消息数据
//			if(message.sum_check == get_length(message.message_content,sizeof(message.message_content)))//进行校验
//			{
//				message_flag = 1;
//			}
//		}
//		//清空接收数据缓冲区，为下次接收做准备
//		memset(usart2_buf,0,sizeof(usart2_buf));
//		usart2_buf_index = 0;	
//	}
//}

/******************************************************************************
函数名：USART3_IRQHandler
功能：串口3中断处理函数,与指纹模块进行通信
输入参数：无
输出参数：无
其他说明：
******************************************************************************/

//串口发送缓存区 	
extern u8 USART3_TX_BUF[USART3_MAX_SEND_LEN]; //发送缓冲,最大USART3_MAX_SEND_LEN字节  
//串口接收缓存区 	
extern u8 USART3_RX_BUF[USART3_MAX_RECV_LEN]; 		//接收缓冲,最大USART3_MAX_RECV_LEN个字节.

extern u16 USART3_RX_STA;  

//通过判断接收连续2个字符之间的时间差不大于100ms来决定是不是一次连续的数据.
//如果2个字符接收间隔超过100ms,则认为不是1次连续数据.也就是超过100ms没有接收到
//任何数据,则表示此次接收完毕.
//接收到的数据状态
//[15]:0,没有接收到数据;1,接收到了一批数据.
//[14:0]:接收到的数据长度


//void USART3_IRQHandler(void)
//{
//	u8 res;	    
//	if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)//接收到数据
//	{	 
//		res =USART_ReceiveData(USART3);
//		if((USART3_RX_STA&(1<<15))==0)//接收完的一批数据,还没有被处理,则不再接收其他数据
//		{ 		
//			if(USART3_RX_STA<USART3_MAX_RECV_LEN)		//还可以接收数据
//			{
//				TIM_SetCounter(TIM7,0);//计数器清空        				 
//				if(USART3_RX_STA==0)		
//				TIM_Cmd(TIM7, ENABLE);  //使能定时器7 
//				USART3_RX_BUF[USART3_RX_STA++]=res;		//记录接收到的值	 
//			}
//			else 
//			{
//				USART3_RX_STA|=1<<15;					//强制标记接收完成
//			} 
//		}
//			//如果USART1的发送缓冲区可用，将数据转发到USART1
//	  while ((USART1->SR & USART_SR_TXE) == RESET); // 等待USART1发送缓冲区准备好
//	  USART_SendData(USART1, res); // 将数据发送到USART1
//	}										 
//}  	


/******************************************************************************
函数名：TIM2_IRQHandler
功能：定时器2中断处理函数---定时化任务
输入参数：无
输出参数：无
其他说明：
******************************************************************************/
//void TIM2_IRQHandler(void)
//{
//	if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
//	{
//		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
//		
//		//'#'键确认输入
//		if(mtri_key_value == '#')
//		{
//			if(password_pattern == 0)	//校验密码模式
//			{
//				if(strcmp(password_input,"***") == 0)
//				{
//					password_pattern = 1;
//					printf("password will be changed,please input super password!\n");
//				}
//				else if(strcmp(password_input,"AAA") == 0)
//				{
//					password_pattern = 1;
//					door_flag = 1;
//				}
//				else if(strcmp(password_input,"BBB") == 0)
//				{
//					password_pattern = 1;
//					door_flag = 2;
//				}
//				else if(strcmp(password[0],password_input) == 0 || strcmp(password[1],password_input) == 0)
//				{
//					printf("password is ok!\n");
//					password_flag = 1;
//				}
//				else
//				{
//					printf("password is error!\n");
//					password_flag = 0;
//				}
//			}
//			else if(password_pattern == 1)	//验证管理员密码模式
//			{
//				if(strcmp(password[0],password_input) == 0)
//				{
//					password_pattern = 2;
//					printf("super password  is ok,pelase input new password\n");
//				}
//				else
//				{
//					password_pattern = 0;
//					printf("super password  is error,will exit\n");
//				}
//			}
//			else if(password_pattern == 2)	
//			{
//				if(door_flag == 0)	//输入新密码
//				{
//					strcpy(password[1],password_input);
//					pwd_change_flag = 1;
//					password_pattern = 0;
//				}
//				else if(door_flag == 1)	//输入需要录入的指纹ID
//				{
//					ID = atoi(password_input);
//				}
//				else if(door_flag == 2)	//输入需要删除的指纹ID
//				{
//					ID = atoi(password_input);
//				}
//			}
//			//清空输入密码数组、清空输入健值、输入密码数组下标置位。	
//			memset(password_input,0,sizeof(password_input));
//			input_pwd_change_flag = 1;
//			password_input_index = 0;
//			mtri_key_value = 0;
//		}
//	}
//}

/**
  * @}
  */ 

/**
  * @}
  */ 


/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
